package org.deng.vertx.springboot.verticle;

import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.ServerWebSocket;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.ext.web.handler.CorsHandler;
import io.vertx.ext.web.handler.ResponseTimeHandler;
import io.vertx.ext.web.handler.StaticHandler;
import lombok.extern.slf4j.Slf4j;
import org.deng.vertx.springboot.config.ProjectEnvEnum;
import org.deng.vertx.springboot.pojo.ResData;
import org.deng.vertx.springboot.util.FastJsonUtils;
import org.deng.vertx.springboot.web.controller.BaseController;
import org.deng.vertx.springboot.web.socket.WebSocketHandler;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * @author 邓力宾
 * @date 2022/12/29 9:11
 * @desc
 */
@Slf4j
@Component
public class WebVerticle extends BaseVerticle implements ApplicationContextAware {
    private ApplicationContext applicationContext;
    private WebSocketHandler webSocketHandler;

    @Autowired
    public void setWebSocketHandler(WebSocketHandler webSocketHandler) {
        this.webSocketHandler = webSocketHandler;
    }

    @Override
    public void start() throws Exception {
        log.info("webVerticle start方法");
        startWeb();
    }

    private void startWeb() {
        //路由
        Router router = Router.router(vertx);

        globalConfig(router);
        //注册controller
        registerController(router);
        Integer port = projectProperties.getPort();
        vertx.createHttpServer()
                .requestHandler(router) //使用路由
                .webSocketHandler(webSocketHandler) //websocket
                .listen(port, http -> {
                    if (http.succeeded()) {
                        log.info("web启动成功，端口:{}", port);
                    } else {
                        log.error("web启动失败", http.cause());
                    }
                });
    }


    /**
     * 全局配置
     *
     * @param router
     */
    private void globalConfig(Router router) {
        //用于处理request body
        BodyHandler bodyHandler = BodyHandler.create()
                .setBodyLimit(-1L) //设置body限制大小
                .setUploadsDirectory(projectProperties.getUploadDir()) //文件上传目录
                .setDeleteUploadedFilesOnEnd(true);//是否删除上传的文件

        router.route().handler(bodyHandler);
        //跨域
        router.route().handler(CorsHandler.create("*")
                .allowedMethod(HttpMethod.GET)
                .allowedMethod(HttpMethod.POST)
                .allowedMethod(HttpMethod.OPTIONS)
                .allowedHeader("Content-Type")//"Content-Type","AccessToken","X-CSRF-Token", "Authorization", "Token","token"
                .allowedHeader("Authorization")
                .allowedHeader("authorization")
                .exposedHeader("Content-Length") //"Content-Length","Access-Control-Allow-Origin","Access-Control-Allow-Headers", "Content-Type", "Date", "token", "Token"
                .exposedHeader("Access-Control-Allow-Origin")
                .exposedHeader("Access-Control-Allow-Headers")
                .exposedHeader("Content-Type")
                .exposedHeader("authorization")
        );

        //错误捕捉
        router.errorHandler(500, ctx -> {
            ctx.failure().printStackTrace();
            log.error("异常捕捉,", ctx.failure());
            writeError(ctx);
        });

        //静态资源
        router.route("/static/*").handler(StaticHandler.create("./webroot").setDefaultContentEncoding("utf-8"));
        //该处理器会将从接收到请求到写入响应的消息头之间的毫秒数写入到响应的 x-response-time 里
        router.route().handler(ResponseTimeHandler.create());

    }

    /**
     * 注册controller
     *
     * @param router
     */
    private void registerController(Router router) {
        Map<String, BaseController> controllerMap = applicationContext.getBeansOfType(BaseController.class);
        log.info("注册controller");
        for (Map.Entry<String, BaseController> entry : controllerMap.entrySet()) {
            entry.getValue().configRouter(router);
        }
    }

    /**
     * 返回错误
     *
     * @param ctx
     */
    private void writeError(RoutingContext ctx) {
        if (projectProperties.getEnvEnum().equals(ProjectEnvEnum.DEV)) {
            ctx.end(FastJsonUtils.toJSONString(ResData.error(ctx.failure().getMessage())));

        } else {
            ctx.end(FastJsonUtils.toJSONString(ResData.error("内部异常")));
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
